package top.zsyle.sycc.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import top.zsyle.sycc.doc.CourseDoc;
import top.zsyle.sycc.domain.*;
import top.zsyle.sycc.dto.CourseDto;
import top.zsyle.sycc.exception.GlobalExceptionEnum;
import top.zsyle.sycc.feign.EsCourseService;
import top.zsyle.sycc.feign.MediaService;
import top.zsyle.sycc.mapper.CourseMapper;
import top.zsyle.sycc.result.JsonResult;
import top.zsyle.sycc.service.*;
import top.zsyle.sycc.utils.AssertUtil;
import top.zsyle.sycc.vo.CourseDetailVo;
import top.zsyle.sycc.vo.CourseInfoVo;
import top.zsyle.sycc.vo.CourseOrderInfoVo;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author zhongshiyi
 * @since 2022-12-31
 */
@Service
public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course> implements ICourseService {

    @Autowired
    private ITeacherService teacherService;
    @Autowired
    private ICourseMarketService courseMarketService;
    @Autowired
    private ICourseDetailService courseDetailService;
    @Autowired
    private ICourseResourceService courseResourceService;
    @Autowired
    private ICourseSummaryService courseSummaryService;
    @Autowired
    private ICourseTypeService courseTypeService;
    @Autowired
    private EsCourseService esCourseService;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    @Autowired
    private CourseMapper courseMapper;
    @Autowired
    private ICourseChapterService courseChapterService;
    @Autowired
    private MediaService mediaService;

    @Override
    @Transactional
    public void save(CourseDto courseDto) {
        Course course = courseDto.getCourse();
        CourseDetail courseDetail = courseDto.getCourseDetail();
        CourseMarket courseMarket = courseDto.getCourseMarket();
        CourseResource courseResource = courseDto.getCourseResource();
        List<Long> teacherIds = courseDto.getTeacherIds();
        //参数校验
        //查询课程是否已经存在，不存在就保存
        selectCourseByName(course);
        //保存course
        saveCourse(course,teacherIds);
        Long courseId = course.getId();
        //保存courseDetail
        saveCourseDetail(courseDetail,courseId);
        //保存courseMarket
        saveCourseMarket(courseMarket,courseId);
        //保存courseResource
        saveCourseResource(courseResource,courseId);
        //保存courseSummary
        saveCourseSummary(courseId);
        //添加课程老师中间表
        courseMapper.addMiddleTea(courseId,teacherIds);
    }

    private void saveCourseSummary(Long courseId) {
        CourseSummary courseSummary = new CourseSummary();
        courseSummary.setId(courseId);
        courseSummaryService.insert(courseSummary);
    }

    /**
     * 上架课程
     * @param id
     */
    @Override
    public void onLineCourse(Long id) {
        //1.参数校验
        //2.业务校验
        //2.1.查询该课程是否存在
        Course course = selectById(id);
        AssertUtil.isNotNull(course,GlobalExceptionEnum.ERROR);
        //2.2.查询该课程是否下架
        AssertUtil.isEquals(Course.OFF_LINE.toString(),course.getStatus().toString(),GlobalExceptionEnum.ERROR);
        //3.将数据保存到es(通过调用es服务)
        CourseDoc courseDoc = new CourseDoc();
        //t_course
        BeanUtils.copyProperties(course,courseDoc);
        //t_course_market
        CourseMarket courseMarket = courseMarketService.selectById(id);
        BeanUtils.copyProperties(courseMarket,courseDoc);
        String chargeName = 1 == courseMarket.getCharge() ? "免费" : "收费";
        courseDoc.setChargeName(chargeName);
        //t_course_summary
        CourseSummary courseSummary = courseSummaryService.selectById(id);
        BeanUtils.copyProperties(courseSummary,courseDoc);
        //t_course_type
        CourseType courseType = courseTypeService.selectById(course.getCourseTypeId());
        courseDoc.setTypeName(courseType.getName());
        courseDoc.setTotalCount(courseType.getTotalCount());
        esCourseService.save(courseDoc);
        //4.修改课程状态
        course.setStatus(Course.ON_LINE);
        course.setOnlineTime(new Date());
        updateById(course);
        //5.给所有的相关用户发消息（使用MQ：结果不重要，可以使用单向消息）
        Message<Course> message = MessageBuilder.withPayload(course).build();
        rocketMQTemplate.sendOneWay("course-topic:notice-tag",message);
    }

    /**
     * 根据课程Id查询课程详情
     *
     * @param id
     * @return
     */
    @Override
    public CourseDetailVo detailData(Long id) {

        /**
         *     private Course course;
         *     private CourseMarket courseMarket;
         *     private List<CourseChapter> courseChapters;
         *     private List<Teacher> teachers;
         *     private CourseDetail courseDetail;
         *     private CourseSummary courseSummary;
         */

        // 1.业务校验
        Course course = selectById(id);
        AssertUtil.isNotNull(course, GlobalExceptionEnum.ERROR);
        AssertUtil.isEquals(Course.ON_LINE.toString(), course.getStatus().toString(), GlobalExceptionEnum.ERROR);
        // 2.封装数据
        CourseMarket courseMarket = courseMarketService.selectById(id);
        CourseDetail courseDetail = courseDetailService.selectById(id);
        CourseSummary courseSummary = courseSummaryService.selectById(id);
        List<Teacher> teachers = courseMapper.selectTeachersByCourseId(id);
        List<CourseChapter> courseChapters = selectCourseChaptersByCourseId(id);

        CourseDetailVo courseDetailVo = new CourseDetailVo();
        courseDetailVo.setCourse(course);
        courseDetailVo.setCourseChapters(courseChapters);
        courseDetailVo.setCourseDetail(courseDetail);
        courseDetailVo.setCourseMarket(courseMarket);
        courseDetailVo.setCourseSummary(courseSummary);
        courseDetailVo.setTeachers(teachers);
        return courseDetailVo;
    }

    /**
     * 生成订单时，课程信息回显
     * @param courseIds
     * @return
     */
    @Override
    public CourseOrderInfoVo info(String courseIds) {
        //1‘校验参数
        String[] split = courseIds.split(",");
        AssertUtil.isTrue(split.length>0,GlobalExceptionEnum.ERROR);
        //1.1符合规范，不为空，全是数字，不能重复
        Set<Long> IdsSet = Arrays.stream(split).filter(courseId -> !StringUtils.isEmpty(courseId)).map(Long::valueOf).collect(Collectors.toSet());
        AssertUtil.isTrue(split.length == IdsSet.size(),GlobalExceptionEnum.ERROR);
        //1.2课程存在，并且已上线
        List<Course> courses = selectBatchIds(IdsSet);
        AssertUtil.isTrue(courses.size() > 0, GlobalExceptionEnum.ERROR);
        //每次进行操作之后都要判断空
        List<Course> onLineCourses = courses.stream().filter(c -> c.getStatus().equals(Course.ON_LINE)).collect(Collectors.toList());
        AssertUtil.isTrue(IdsSet.size() == onLineCourses.size(), GlobalExceptionEnum.ERROR);
        //得到总价格 totalAmount
        BigDecimal price = new BigDecimal(0);
        // 3.初始化装数据容器
        List<CourseInfoVo> courseInfoVos = new ArrayList<>();
        for (Course onLineCoures : onLineCourses) {
            CourseInfoVo courseInfoVo = new CourseInfoVo();
            courseInfoVo.setCourse(onLineCoures);
            CourseMarket courseMarket = courseMarketService.selectById(onLineCoures.getId());
            courseInfoVo.setCourseMarket(courseMarket);
            courseInfoVos.add(courseInfoVo);
            //计算总金额
            price = price.add(courseMarket.getPrice());
        }
        CourseOrderInfoVo courseOrderInfoVo = new CourseOrderInfoVo();
        courseOrderInfoVo.setCourseInfos(courseInfoVos);
        courseOrderInfoVo.setTotalAmount(price);
        return courseOrderInfoVo;
    }

    private List<CourseChapter> selectCourseChaptersByCourseId(Long id) {
        // 1.根据课程Id查询所有章节
        List<CourseChapter> courseChapters = courseChapterService.listByCourseId(id);
        // 2.根据课程Id查询课程的所有视频
        JsonResult jsonResult = mediaService.getMediaFileByCourseId(id);
        AssertUtil.isTrue(jsonResult.isSuccess(), GlobalExceptionEnum.ERROR);
        AssertUtil.isNotNull(jsonResult.getData(), GlobalExceptionEnum.ERROR);
        List<MediaFile> mediaFiles = JSON.parseArray(JSON.toJSONString(jsonResult.getData()), MediaFile.class);
        // 3.为了减少双重for循环，将课程章节集合转换为map
        Map<Long, CourseChapter> courseChapterMap = courseChapters.stream().collect(Collectors.toMap(CourseChapter::getId, courseChapter -> courseChapter));
        // 4.根据每个mediaFile的chapterId找到自己的chapter对象，放入到chapter对象的mediaFile集合中
        mediaFiles.forEach(e -> {
                    e.setFileUrl("");
                    courseChapterMap.get(e.getChapterId()).getMediaFiles().add(e);
                }
        );
        // 5.返回组装好的章节集合数据
        return courseChapters;
    }


    private void saveCourseResource(CourseResource courseResource,Long courseId) {
        courseResource.setCourseId(courseId);
        courseResourceService.insert(courseResource);
    }

    private void saveCourseMarket(CourseMarket courseMarket,Long courseId) {
        courseMarket.setId(courseId);
        courseMarketService.insert(courseMarket);
    }

    private void saveCourseDetail(CourseDetail courseDetail,Long courseId) {
        courseDetail.setId(courseId);
        courseDetailService.insert(courseDetail);
    }

    private void saveCourse(Course course,List<Long> teacherIds) {
        course.setStatus(Course.OFF_LINE);
        course.setLoginId(1L);
        course.setLoginUserName("yhptest1");
        List<Teacher> teachers = teacherService.selectBatchIds(teacherIds);
        String teacherNames = teachers.stream().map(Teacher::getName).collect(Collectors.joining(","));
        course.setTeacherNames(teacherNames);
        insert(course);
    }

    private void selectCourseByName(Course course) {
        Wrapper<Course> wrapper = new EntityWrapper<>();
        wrapper.eq("name", course);
        Course one = selectOne(wrapper);
        AssertUtil.isNull(one, GlobalExceptionEnum.COMM_COURSE_IS_EXIST_EXCEPTION);
    }
}
